from typing import Any, AsyncIterable

import requests
from fastapi import Response
from starlette.responses import StreamingResponse

from .models import RecognitionRequest, RecognitionResponse
from server.postprocessing import formatter
from ..preprocessing import stream, video, image

from server.inference import client

from server.utils import generate_request_id, handle_error

async def handle_recognition_request(request_data: RecognitionRequest, response: Response) -> Any:
    """
    处理识别请求的异步函数。

    参数:
    - request_data: RecognitionRequest 类型，包含请求的具体数据和类型。
    - response: Response 类型，用于返回处理结果的响应对象。

    返回值:
    - Any 类型，通常为 RecognitionResponse 对象，包含处理结果和请求ID。
    """
    request_id = generate_request_id()  # 生成唯一的请求ID

    try:
        # 根据请求类型进行预处理
        PREPROCESSORS = {
            "image": image.ImagePreprocessor,
            "video": video.VideoPreprocessor,
            "stream": stream.StreamPreprocessor,
        }

        #读取 url 文件
        response = requests.get(request_data.url)
        bytes_data = response.content
        preprocessed_data = PREPROCESSORS[request_data.type].preprocess(bytes_data)

        # 向Triton发送数据进行推理
        inference_result = await client.TritonInferenceClient("my_model_1").run_inference(preprocessed_data)

        # 对推理结果进行后处理
        #processed_result = POSTPROCESSORS[request_data.type](inference_result)
        processed_result = formatter.format_as_json(inference_result)


        # 将处理结果封装为JSON响应返回
        return RecognitionResponse(result=processed_result, request_id=request_id)

    except Exception as e:
        # 处理异常，并通过response返回错误信息
        handle_error(e, request_id, response)


async def stream_recognition_response(request_id: str, processed_result: AsyncIterable[Any]) -> Response:
    """
    异步生成流式识别响应。

    参数:
    - request_id: 请求的唯一标识符，类型为字符串。
    - processed_result: 处理后的结果，为一个异步可迭代对象。

    返回值:
    - 返回一个响应对象，其中包含处理后的结果以流的形式返回，文件名基于请求ID。
    """

    # 设置响应头部，指定内容-Disposition为附件，并以请求ID为后缀生成文件名
    headers = {"Content-Disposition": f"attachment; filename=result_{request_id}.json"}

    # 返回一个流式响应，内容为处理后的结果，媒体类型为JSON
    return StreamingResponse(processed_result, media_type="application/json", headers=headers)


def handle_error(exception: Exception, request_id: str, response: Response):
    """
    处理异常并定制错误响应。

    参数:
    exception - 发生的异常对象。
    request_id - 请求的唯一标识符。
    response - 用于返回定制错误信息的响应对象。

    返回值:
    无返回值，直接修改了传入的response对象。
    """
    # 生成错误信息，包含请求ID和异常信息
    error_message = f"Request ID {request_id}: {exception}"
    print(error_message)  # 使用日志框架记录更详细的错误信息
    # 设置响应状态码为500，表示服务器内部错误
    response.status_code = 500
    # 将错误信息设置为响应体的内容
    response.body = error_message

